package br.ufpe.cin.vspeed.gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle;

import prefuse.Display;
import br.ufpe.cin.vspeed.integration.CommunicationManager;
import br.ufpe.cin.vspeed.integration.NodeGeneric;
import br.ufpe.cin.vspeed.view.ConsolidadorInfoPrefuse;

/**
 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
 */
public class PanelViewNetwork extends javax.swing.JPanel {

	private static final long serialVersionUID = 1L;
	private JScrollPane jScrollPaneNetwork;
	private JProgressBar jProgressBar;

	private JCheckBox jCheckBoxHidePI;
	private JCheckBox jCheckBoxHidePD;

	private boolean isPDShow = true;
	private boolean isPIShow = true;

	private ConsolidadorInfoPrefuse consolidadorInfoPrefuse;

	private final Object mutex = new Object();

	public PanelViewNetwork() {
		super();
		initGUI();
		drawTopologyMap(true, true);
	}

	private void initGUI() {
		try {
			GroupLayout thisLayout = new GroupLayout((JComponent)this);
			this.setLayout(thisLayout);
			setPreferredSize(new java.awt.Dimension(766, 704));
			setBackground(new java.awt.Color(255, 255, 255));
			setOpaque(false);
			{
				this.jProgressBar = new JProgressBar();
				this.jProgressBar.setBounds(0, 659, 747, 24);
			}
			{
				this.jScrollPaneNetwork = new JScrollPane();
				this.jScrollPaneNetwork.getHorizontalScrollBar().setBounds(0, 0, 0, 0);
				this.jScrollPaneNetwork.getVerticalScrollBar().setBounds(0, 0, 0, 0);
				this.jScrollPaneNetwork.setLayout(null);
				this.jScrollPaneNetwork.setBorder(BorderFactory.createTitledBorder("Network"));
				this.jScrollPaneNetwork.setEnabled(false);
				this.jScrollPaneNetwork.setForeground(new java.awt.Color(255, 255, 255));
				this.jScrollPaneNetwork.setBackground(new java.awt.Color(255, 255, 255));
			}
			{
				this.jCheckBoxHidePD = new JCheckBox();
				this.jCheckBoxHidePD.setText("Hide Data Peers");
				this.jCheckBoxHidePD.setOpaque(false);

				this.jCheckBoxHidePD.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(final ActionEvent e) {
						treatPDActions();
					}
				});
			}
			{
				this.jCheckBoxHidePI = new JCheckBox();
				this.jCheckBoxHidePI.setText("Hide Integration Peers");
				this.jCheckBoxHidePI.setOpaque(false);
				this.jCheckBoxHidePI.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(final ActionEvent e) {
						treatPIActions();
					}
				});
			}
			thisLayout.setVerticalGroup(thisLayout.createSequentialGroup()
				.addContainerGap()
				.addGroup(thisLayout.createParallelGroup()
				    .addComponent(jScrollPaneNetwork, GroupLayout.Alignment.LEADING, GroupLayout.PREFERRED_SIZE, 638, GroupLayout.PREFERRED_SIZE)
				    .addGroup(GroupLayout.Alignment.LEADING, thisLayout.createSequentialGroup()
				        .addGap(26)
				        .addComponent(jCheckBoxHidePD, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE)
				        .addGap(21)
				        .addComponent(jCheckBoxHidePI, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
				        .addGap(545)))
				.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
				.addComponent(jProgressBar, 0, 38, Short.MAX_VALUE)
				.addContainerGap());
			thisLayout.setHorizontalGroup(thisLayout.createSequentialGroup()
				.addContainerGap()
				.addGroup(thisLayout.createParallelGroup()
				    .addComponent(jProgressBar, GroupLayout.Alignment.LEADING, 0, 542, Short.MAX_VALUE)
				    .addComponent(jScrollPaneNetwork, GroupLayout.Alignment.LEADING, 0, 542, Short.MAX_VALUE))
				.addGap(20)
				.addGroup(thisLayout.createParallelGroup()
				    .addComponent(jCheckBoxHidePD, GroupLayout.Alignment.LEADING, 0, 188, Short.MAX_VALUE)
				    .addComponent(jCheckBoxHidePI, GroupLayout.Alignment.LEADING, 0, 188, Short.MAX_VALUE))
				.addContainerGap());
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	private void treatPDActions() {
		this.isPDShow = this.isPDShow == true ? false : true;

		drawTopologyMap(this.isPDShow, this.isPIShow);
	}

	private void treatPIActions() {
		this.isPIShow = this.isPIShow == true ? false : true;

		drawTopologyMap(this.isPDShow, this.isPIShow);
	}

	private void drawTopologyMap(final boolean showPD, final boolean showPI) {
		this.jProgressBar.setIndeterminate(true);

		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					initializeTopology();
					Thread.sleep(3000);
				} catch (final InterruptedException e) {
					e.printStackTrace();
				}
				final CommunicationManager manager = CommunicationManager.getInstance();
				manager.recoveryTopologyInfo();

				final NodeGeneric genericPeer = manager.getGenericPeer();

				final Display d = PanelViewNetwork.this.consolidadorInfoPrefuse.gerarDisplay(
						genericPeer.getMapAddressReduzido_NodeInfo(), showPD, showPI);
				PanelViewNetwork.this.jScrollPaneNetwork.removeAll();
				PanelViewNetwork.this.jScrollPaneNetwork.add(d);

				synchronized (PanelViewNetwork.this.mutex) {
					PanelViewNetwork.this.mutex.notify();
				}
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (PanelViewNetwork.this.mutex) {
					try {
						PanelViewNetwork.this.mutex.wait();
						PanelViewNetwork.this.jProgressBar.setIndeterminate(false);
					} catch (final InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}

	/**
	 * Prepare the results information and map result information
	 */
	private void initializeTopology() {
		final Runnable plotaTopologia = new Runnable() {
			@Override
			public void run() {
				PanelViewNetwork.this.consolidadorInfoPrefuse = new ConsolidadorInfoPrefuse(null);
				final CommunicationManager manager = CommunicationManager.getInstance();
				manager.sendPrepareTopolyMessage();
			}
		};

		final Thread tPlotaTopologia = new Thread(plotaTopologia);
		tPlotaTopologia.start();
	}
}
